package com.old.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import okio.ByteString;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;

public class XunfeiVoiceUtil {
    // 语音听写（流式版）配置
    private static final String STT_HOST = "wss://iat-api.xfyun.cn/v2/iat";
    private static final String STT_APPID = "f6323c10";
    private static final String STT_API_SECRET = "ZmEyNWY1M2U0ZGE4MmI5NDQwYTE2Njcz";
    private static final String STT_API_KEY = "3dd5aa5d27843fb247f4a70a5f688e96";

    // 语音合成配置
    private static final String TTS_HOST = "https://tts-api.xfyun.cn/v2/tts";

    // 流式语音识别
    public static String sttStream(MultipartFile audioFile) throws Exception {
        CountDownLatch latch = new CountDownLatch(1);
        StringBuilder result = new StringBuilder();

        // 1. 生成鉴权URL
        String authUrl = getAuthUrl(STT_HOST, STT_API_KEY, STT_API_SECRET);
        OkHttpClient client = new OkHttpClient.Builder().build();
        Request request = new Request.Builder().url(authUrl).build();

        // 2. 创建WebSocket连接
        WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                // 发送音频参数
                JSONObject params = new JSONObject();
                params.put("common", new JSONObject()
                        .fluentPut("app_id", STT_APPID));
                JSONObject business = new JSONObject()
                        .fluentPut("language", "zh_cn")
                        .fluentPut("domain", "iat")
                        .fluentPut("accent", "mandarin");
                params.put("business", business);
                params.put("data", new JSONObject()
                        .fluentPut("status", 0)
                        .fluentPut("format", "audio/L16;rate=16000")
                        .fluentPut("encoding", "raw"));
                webSocket.send(params.toJSONString());

                // 发送音频数据
                try (InputStream is = audioFile.getInputStream()) {
                    byte[] buffer = new byte[1280]; // 每次发送40ms数据（16k采样率）
                    while (is.read(buffer) != -1) {
                        webSocket.send(ByteString.of(buffer));
                    }
                    // 发送结束标识
                    webSocket.send(new JSONObject()
                            .fluentPut("data", new JSONObject()
                                    .fluentPut("status", 2))
                            .toJSONString());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onMessage(WebSocket webSocket, String text) {
                JSONObject resp = JSON.parseObject(text);
                if (resp.getJSONObject("data") != null) {
                    result.append(resp.getJSONObject("data").getString("result"));
                }
                if (resp.getInteger("code") == 0 && resp.getJSONObject("data").getInteger("status") == 2) {
                    latch.countDown();
                }
            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                latch.countDown();
            }
        });

        latch.await();
        return result.toString();
    }

    // 语音合成（流式版）
    public static InputStream ttsStream(String text) throws Exception {
        OkHttpClient client = new OkHttpClient.Builder().build();
        String authUrl = getAuthUrl(TTS_HOST, STT_API_KEY, STT_API_SECRET);

        JSONObject requestBody = new JSONObject()
                .fluentPut("common", new JSONObject().fluentPut("app_id", STT_APPID))
                .fluentPut("business", new JSONObject()
                        .fluentPut("aue", "lame")
                        .fluentPut("sfl", 1)
                        .fluentPut("vcn", "xiaoyan"))
                .fluentPut("data", new JSONObject()
                        .fluentPut("text", Base64.getEncoder().encodeToString(text.getBytes()))
                        .fluentPut("status", 2));

        Request request = new Request.Builder()
                .url(authUrl)
                .post(RequestBody.create(requestBody.toJSONString(), MediaType.get("application/json")))
                .build();

        try (Response response = client.newCall(request).execute()) {
            return response.body().byteStream();
        }
    }

    private static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        // ...复用BigModelNewUtil的鉴权方法...
        // 鉴权方法
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
        // System.err.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);

        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
        // System.err.println(sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

        // System.err.println(httpUrl.toString());
        return httpUrl.toString();
    }
}

